package util.shaders;

import general.AllocableResource;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import javax.media.opengl.GL;

import util.BasicGraphicsJogl;

public class Shader implements AllocableResource
{
	static private ShaderManager shaderManager = new ShaderManager(true);
	private int shaderType;
	private String resourceName;
	private int shaderHandle = 0;
	
	public static Shader getAllocatedShader(int shaderType,String resourceName)
	{
		return shaderManager.getAllocatedResource(new Shader(shaderType,resourceName));
	}
	public void release()
	{
		shaderManager.release(this);
	}
	
	private Shader(int shaderType,String resourceName)
	{
		this.shaderType = shaderType;
		this.resourceName = resourceName;
	}
	
	@Override
	public void allocate()
	{
		BasicGraphicsJogl basicGraphics = BasicGraphicsJogl.instance();
		GL gl = basicGraphics.getGL();
		shaderHandle = gl.glCreateShaderObjectARB(shaderType);
		String shaderSource = "";
		try
		{
			InputStream inStream = getClass().getResourceAsStream(resourceName);
			InputStreamReader inStreamReader = new InputStreamReader(inStream, "UTF-8");
			final char[] buffer = new char[1024];
			StringBuilder readString = new StringBuilder();
			
    		int numCharsRead;    		
			while((numCharsRead = inStreamReader.read(buffer, 0, 1024)) != -1)
			{
				readString.append(buffer, 0, numCharsRead);
			}
			shaderSource  = readString.toString();
		} 
		catch (IOException e)
		{
			assert false: e.toString();
		}
		
		
		gl.glShaderSourceARB(shaderHandle, 1, new String[] {shaderSource}, null);
		gl.glCompileShaderARB(shaderHandle);
		basicGraphics.assertShaderStatus(shaderHandle,GL.GL_COMPILE_STATUS);
		
	}
	@Override
	public void destroy()
	{
		BasicGraphicsJogl basicGraphics = BasicGraphicsJogl.instance();
		GL gl = basicGraphics.getGL();
		if(shaderHandle != 0)
		{
			gl.glDeleteShader(shaderHandle);
		}
	}
	@Override
	public boolean equals(Object object)
	{
		Shader shader = (Shader)object;
		return (shaderType == shader.shaderType) && (resourceName.equals(shader.resourceName));
	}
	@Override
	public int hashCode()
	{
		return shaderType + 31 * resourceName.hashCode();
	}

	public int getHandle()
	{
		return shaderHandle;
	}
}
